package seatiger.tomcat.catalina.connector;

import seatiger.tomcat.catalina.Constants;
import seatiger.tomcat.catalina.Request;
import seatiger.tomcat.catalina.Response;
import seatiger.tomcat.util.StringManager;

import javax.servlet.ServletOutputStream;
import javax.servlet.ServletResponse;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;

/**
 * 一些基础实现
 */
@Deprecated
public abstract class ResponseBase implements Response, ServletResponse {

    protected Request request = null;

    protected OutputStream output = null;

    protected PrintWriter writer;

    protected ServletOutputStream stream = null;

    /**
     * 发送数据的缓存
     */
    protected byte[] buffer = new byte[1024];

    /**
     * buffer中的数量
     */
    protected int bufferCount = 0;

    protected int contentLength = -1;

    protected String contentType = null;

    /**
     * 已经提前响应过一次内容了
     */
    protected boolean committed = false;

    protected ResponseFacade facade = new ResponseFacade(this);


    protected static StringManager sm =
            StringManager.getManager(Constants.PACKAGE_CONNECTOR);

    @Override
    public void setRequest(Request request) {
        this.request = request;
    }

    @Override
    public Request getRequest() {
        return request;
    }

    @Override
    public void setStream(OutputStream stream) {
        this.output = stream;
    }

    @Override
    public OutputStream getStream() {
        return output;
    }

    /**
     * 获取PrintWriter，如果已经调用了getOutputStream()方法，那么就报错
     * @return
     * @throws IOException
     */
    @Override
    public PrintWriter getWriter() throws IOException {
        if (writer != null){
            return writer;
        }
        if (stream != null){
            throw new IllegalStateException("responseBase.getWriter.ise");
        }
        ResponseStream newStream = (ResponseStream) createOutputStream();
        newStream.setCommit(false);
        OutputStreamWriter outputStreamWriter = new OutputStreamWriter(newStream);
        writer = new ResponseWriter(outputStreamWriter,newStream);
        stream = newStream;
        return writer;
    }

    /**
     * 如果已经获调用了getWriter() 方法，那么就报错
     * @return
     * @throws IOException
     */
    @Override
    public ServletOutputStream getOutputStream() throws IOException {
        if (writer != null){
            throw new IllegalStateException("responseBase.getOutputStream.ise");
        }
        if (stream == null){
            stream = createOutputStream();
        }
        ((ResponseStream) stream).setCommit(true);
        return stream;
    }

    @Override
    public ServletOutputStream createOutputStream() throws IOException {
        return new ResponseStream(this);
    }

    @Override
    public void recycle() {
        bufferCount = 0;
        committed = false;
        contentLength = -1;
        contentType = null;
        output = null;
        request = null;
        stream = null;
        writer = null;
    }

    /**
     * 将相应数据写入缓冲区中
     * @param b
     * @throws IOException
     */
    public void write(int b) throws IOException {
        //数据已经满了，需要提前刷出
        if (bufferCount >= buffer.length){
            flushBuffer();
        }
        buffer[bufferCount++] = (byte) b;
    }

    /**
     * 将相应数据写入缓冲区中
     * @param b
     * @param off
     * @param len
     * @throws IOException
     */
    public void write(byte b[], int off, int len) throws IOException {
        if (len == 0){
            return;
        }
        //如果buffer缓冲区空间足够，就写入缓冲区
        if (len <= (buffer.length - bufferCount)) {
            System.arraycopy(b, off, buffer, bufferCount, len);
            bufferCount += len;
            return;
        }
        //将数据刷出
        flushBuffer();
        //将数据分批次
        int iterations = len / buffer.length;
        int leftoverStart = iterations * buffer.length;
        int leftoverLen = len - leftoverStart;
        for (int i = 0; i < iterations; i++){
            write(b, off + (i * buffer.length), buffer.length);
        }
        if (leftoverLen > 0) {
            write(b, off + leftoverStart, leftoverLen);
        }
    }

    @Override
    public void flushBuffer() throws IOException {
        committed = true;
        if (bufferCount > 0){
            try {
                output.write(buffer, 0, bufferCount);
                System.out.println(new String(buffer,0,bufferCount));
            }finally {
                bufferCount = 0;
            }
        }
    }

    /**
     * 这里的flush() 会将缓存在buffer中的报文体刷出
     * 将流关闭
     * @throws IOException
     */
    @Override
    public void finishResponse() throws IOException {
        if (stream == null){
            ServletOutputStream sos = getOutputStream();
            sos.flush();
            sos.close();
            return;
        }
        //通道已经关闭了
        if (((ResponseStream) stream).isClosed()){
            return;
        }
        if (writer != null){
            writer.flush();
            writer.close();
        }else {
            stream.flush();
            stream.close();
        }
    }

    /**
     * 表示数据已近提前刷出过一次了
     * @return
     */
    @Override
    public boolean isCommitted() {
        return committed;
    }


    @Override
    public void setContentLength(int length) {
        if (isCommitted()){
            return;
        }
        this.contentLength = length;
    }

    @Override
    public int getContentLength() {
        return contentLength;
    }

    @Override
    public String getContentType() {
        return contentType;
    }

    @Override
    public void setContentType(String contentType) {
        if (isCommitted()){
            return;
        }
        this.contentType = contentType;
    }

    @Override
    public ServletResponse getResponse() {
        return facade;
    }

    @Override
    public void resetBuffer() {
        if (committed)
            throw new IllegalStateException
                    (sm.getString("responseBase.resetBuffer.ise"));
        bufferCount = 0;
    }
}
